package it.uniroma2.exp.dtk;

import it.uniroma2.exp.AbstractExperiment;
import it.uniroma2.util.math.ArrayMath;
import it.uniroma2.util.vector.RandomVectorGenerator;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;

public class SpaceTester extends AbstractExperiment {
	
	private ArrayList<double[]>[] vectors;
	private double[] epsilons = new double[0];
	private boolean unlimited = false;
	
	public void setEpsilons(double[] epsilons) {
		Arrays.sort(epsilons);
		this.epsilons = epsilons;
	}
	
	public void setUnlimited(boolean unlimited) {
		this.unlimited = unlimited;
	}
	
	public void printCount() {
		for (int i=0; i<epsilons.length; i++)
			out.println("Found (at least) "+vectors[i].size()+" vectors with dot product < "+epsilons[i]);
	}

	@SuppressWarnings("unchecked")
	@Override
	protected void runExperiment() throws Exception {
		RandomVectorGenerator rvg = new RandomVectorGenerator(vectorSize, randomOffset);
		if (vectors == null) {
			vectors = new ArrayList[epsilons.length];
			for (int i=0; i<epsilons.length; i++)
				vectors[i] = new ArrayList<double[]>();
		}
		else
			for (ArrayList<double[]> vector : vectors)
				vector.clear();
		int c = 0, i = 0;
		while (c < vectorSize || unlimited) {
			if (i++ % 1000 == 0)
				out.print(".");
			double[] newVector = rvg.generateRandomVector();
			boolean atLeastOneOk = false;
			for (int k=epsilons.length-1; k>=0; k--) {
				boolean ok = true;
				for (double[] oldVector : vectors[k])
					if (ArrayMath.dot(oldVector, newVector) >= epsilons[k]) {
						ok = false;
						break;
					}
				if (ok) {
					atLeastOneOk = true;
					vectors[k].add(newVector);
				}
				else
					break;
			}
			if (atLeastOneOk)
				c = 0;
			else
				c++;
		}
		out.println();
		printCount();
	}

	/**
	 * @param args t to keep searching for new vectors until execution is interrupted
	 */
	public static void main(String[] args) {
		final SpaceTester st = new SpaceTester();
		if (args.length > 0 && args[0].equalsIgnoreCase("t")) {
			st.setUnlimited(true);
			Runtime.getRuntime().addShutdownHook(new Thread() {
				@Override
				public void run() {
					st.printCount();
				}
			});
		}
		try {
			st.setOutputStream(new PrintStream(new File("space_tester.dat")));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.exit(0);
		}
		st.setVectorSizeArray(new int[] {4096, 8192});
		st.setEpsilons(new double[] {0.01, 0.05});
		st.runAll();
	}

}
